#include <wx/dialog.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include "filter_dialog.h"
#include "keyword.h"
#include "debug.h"
#include "util.h"
#include "note_filter.h"
#include "note.h"
#include "settings.h"

class FilterDialog : public wxDialog
{
private:
    wxTextCtrl *keyword_box;
    wxTextCtrl *from_date_box;
    wxTextCtrl *to_date_box;
    wxTextCtrl *body_box;
    wxTextCtrl *max_notes_box;

    wxStaticText *keyword_text;
    wxStaticText *from_date_text;
    wxStaticText *to_date_text;
    wxStaticText *body_text;
    wxStaticText *max_notes_text;

    NoteFilter *result;
    FilterDialogStyle style;

public:
    FilterDialog(NoteFilter* init_filter, const wxString& caption, FilterDialogStyle style=FILTERDIALOG_RANGE);
    void OnOK(wxCommandEvent& event);
    void OnCancel(wxCommandEvent& event);
    bool Show();

    DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(FilterDialog, wxDialog)
    EVT_BUTTON(wxID_CANCEL, FilterDialog::OnCancel)
    EVT_BUTTON(wxID_OK, FilterDialog::OnOK)
END_EVENT_TABLE()

FilterDialog::FilterDialog(NoteFilter* init, const wxString& caption, FilterDialogStyle style)
        : wxDialog(0, -1, caption, wxDefaultPosition, wxSize(400, 300), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
{
    dbgenter("FilterDialog(filter=%s, caption=%s)\n", init->ToString(), caption);
    dbg("test\n");

    this->style = style;
    this->result = init;

    wxString init_max_notes = wxString::Format("%ld", init->max_notes);

    wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
    wxFlexGridSizer *sizer = new wxFlexGridSizer(2);
    wxBoxSizer *btnsizer = new wxBoxSizer(wxHORIZONTAL);


    if (style==FILTERDIALOG_RANGE) {

        keyword_text    = new wxStaticText(this, -1, _("&Keyword:"));
        keyword_box     = new wxTextCtrl  (this, -1, init->KeywordsToString());
        sizer->Add(keyword_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
        sizer->Add(keyword_box,  1, wxEXPAND | wxALL, 2);
        keyword_box->SetFocus();

        from_date_text  = new wxStaticText(this, -1, _("&From:"));
        from_date_box   = new wxTextCtrl  (this, -1, init->from_date);
        sizer->Add(from_date_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
        sizer->Add(from_date_box,  1, wxEXPAND | wxALL, 2);

        to_date_text    = new wxStaticText(this, -1, _("&To:"));
        to_date_box     = new wxTextCtrl  (this, -1, init->to_date);
        sizer->Add(to_date_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
        sizer->Add(to_date_box,  1, wxEXPAND | wxALL, 2);

    } else if (style==FILTERDIALOG_DATE) {

        from_date_text  = new wxStaticText(this, -1, _("&Date:"));
        from_date_box   = new wxTextCtrl  (this, -1, init->from_date);
        sizer->Add(from_date_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
        sizer->Add(from_date_box,  1, wxEXPAND | wxALL, 2);
        from_date_box->SetFocus();

        to_date_box = 0;
        to_date_text = 0;

        keyword_text    = new wxStaticText(this, -1, _("&Keyword:"));
        keyword_box     = new wxTextCtrl  (this, -1, init->KeywordsToString());
        sizer->Add(keyword_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
        sizer->Add(keyword_box,  1, wxEXPAND | wxALL, 2);

    } else {
        ErrMsg("Internal error: Invalid FilterDialogStyle");
    }
    body_text       = new wxStaticText(this, -1, _("&Body:"));
    body_box        = new wxTextCtrl  (this, -1, init->body);
    sizer->Add(body_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
    sizer->Add(body_box,  1, wxEXPAND | wxALL, 2);

    max_notes_text  = new wxStaticText(this, -1, _("&Max:"));
    max_notes_box   = new wxTextCtrl  (this, -1, init_max_notes);
    sizer->Add(max_notes_text, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, 2);
    sizer->Add(max_notes_box,  1, wxEXPAND | wxALL, 2);

    // buttons
    wxButton *btn_ok     = new wxButton(this, wxID_OK,     _("&OK"));
    wxButton *btn_cancel = new wxButton(this, wxID_CANCEL, _("&Cancel"));
    btnsizer->AddStretchSpacer();
    btnsizer->Add(btn_ok,     0, wxALL,  3);
    btnsizer->Add(btn_cancel, 0, wxALL, 3);
    btn_ok->SetDefault();

    // sizers
    sizer->AddGrowableCol(1, 1);
    topsizer->Add(sizer,    1, wxALL | wxEXPAND, 10);
    topsizer->Add(btnsizer, 0, wxALL | wxEXPAND,  5);
    SetSizeHints(this->GetSize().x, this->GetSize().y);
    SetSizer(topsizer);

    Centre();
    SetEscapeId(wxID_CANCEL);
}

bool FilterDialog::Show()
{
    dbgenter("FilterDialog::Show()\n");
    return ShowModal()==wxID_OK;
}

void FilterDialog::OnCancel(wxCommandEvent& event)
{
    dbgenter("FilterDialog::OnCancel()\n");
    EndModal(wxID_CANCEL);
}

void FilterDialog::OnOK(wxCommandEvent& event)
{
    NoteFilter filter;
    if (!CheckFilterDate(from_date_box->GetValue())) {
        wxMessageBox(_("Incorrect format of FROM date"), _("Error"));
        return;
    }
    filter.from_date = from_date_box->GetValue();

    if (!max_notes_box->GetValue().ToLong(&filter.max_notes)) {
        wxMessageBox(_("Invalid format of MAX field"), _("Error"));
        return;
    }
    if (filter.max_notes < 1 || filter.max_notes > 500) {
        wxMessageBox(_("Invalid value of MAX field"), _("Error"));
        return;
    }

    if (style == FILTERDIALOG_RANGE) {
        if (!CheckFilterDate(to_date_box->GetValue())) {
            wxMessageBox(_("Incorrect format of TO date"), _("Error"));
            return;
        }
        filter.to_date = to_date_box->GetValue();
    } else {
        if (!GetEndDate(filter.from_date, &filter.to_date)) {
            ErrMsg(_("Invalid date for single date filtering"));
            return;
        }
    }

    if (!filter.KeywordsFromString(keyword_box->GetValue())) {
        ErrMsg(wxT("Invalid keyword list"));
        return;
    }

    filter.body = body_box->GetValue();

    *result = filter;

    EndModal(wxID_OK);
}

bool GetNoteFilter(const wxString& caption, NoteFilter* filter, FilterDialogStyle style)
{
    FilterDialog *dlg = new FilterDialog(filter, caption, style);
    bool retval = dlg->Show();
    dlg->Destroy();
    return retval;
}
